﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Globalization;
using System.Xml;
using System.Text.RegularExpressions;

namespace Possan.Localization
{
	internal class XmlLibraryNamespace
	{
		List<XmlLibraryPhrase> m_phrases;
		XmlLibraryProvider m_library;

		public XmlLibraryNamespace(XmlLibraryProvider lib)
		{
			m_library = lib;
			m_phrases = new List<XmlLibraryPhrase>();
		}

		public string GetPhrase(string originalphrase)
		{
			return GetPhrase(originalphrase, CultureInfo.CurrentUICulture);
		}

		public string GetPhrase(string originalphrase, CultureInfo locale)
		{
			return GetPhrase(originalphrase, locale.Name);
		}

		public string GetPhrase(string originalphrase, string locale)
		{
			string locale2 = "";
			if (locale.Contains("-"))
			{
				locale2 = locale.Substring(0, locale.IndexOf("-"));
			}
#if DEBUG
			Console.WriteLine(string.Format("XmlLibraryNamespace::GetPhrase( originalphrase=\"{0}\", locale=\"{1}\" ) (locale2={2})", originalphrase, locale, locale2));
#endif
			if (m_library.DefaultLocale != CultureInfo.InvariantCulture)
			{
				foreach (XmlLibraryPhrase p in m_phrases)
				{
					if (p.Translations[m_library.DefaultLocale.Name] == originalphrase)
					{
						if (locale != "")
						{
							if (p.Translations.ContainsKey(locale))
							{
#if DEBUG
								Console.WriteLine(string.Format("XmlLibraryNamespace::GetPhrase returning \"{0}\"", p.Translations[locale]));
#endif
								return p.Translations[locale];
							}

						}
						if (locale2 != "")
						{
							if (p.Translations.ContainsKey(locale2))
							{
#if DEBUG
								Console.WriteLine(string.Format("XmlLibraryNamespace::GetPhrase returning \"{0}\" (locale2)", p.Translations[locale2]));
#endif
								return p.Translations[locale2];
							}
						}
					}
				}
			}
			else
			{
				foreach (XmlLibraryPhrase p in m_phrases)
				{
					if (p.TempOriginalPhrase == originalphrase)
					{
						if (locale != "")
						{
							if (p.Translations.ContainsKey(locale))
							{
#if DEBUG
								Console.WriteLine(string.Format("XmlLibraryNamespace::GetPhrase returning \"{0}\"", p.Translations[locale]));
#endif
								return p.Translations[locale];
							}

						}
						if (locale2 != "")
						{
							if (p.Translations.ContainsKey(locale2))
							{
#if DEBUG
								Console.WriteLine(string.Format("XmlLibraryNamespace::GetPhrase returning \"{0}\" (locale2)", p.Translations[locale2]));
#endif
								return p.Translations[locale2];
							}
						}
					}
				}
			}

#if DEBUG
			Console.WriteLine(string.Format("XmlLibraryNamespace::GetPhrase returning \"{0}\" (fallback)", originalphrase));
#endif
			return originalphrase;
		}

		public string GetPhraseByID(string id, string fallbackphrase, string locale)
		{

			string locale2 = "";
			if (locale.Contains("-"))
			{
				locale2 = locale.Substring(0, locale.IndexOf("-"));
			}

#if DEBUG
			Console.WriteLine(string.Format("XmlLibraryNamespace::GetPhraseByID( id=\"{0}\", fallbackphrase=\"{1}\" locale=\"{2}\" ) (locale2={3})", id, fallbackphrase, locale, locale2));
#endif
			foreach (XmlLibraryPhrase p in m_phrases)
			{
				if (p.ID == id)
				{
					if (locale != "")
					{
						if (p.Translations.ContainsKey(locale))
						{
#if DEBUG
							Console.WriteLine(string.Format("XmlLibraryNamespace::GetPhraseByID returning \"{0}\"", p.Translations[locale]));
#endif
							return p.Translations[locale];
						}
					}
					if (locale2 != "")
					{
						if (p.Translations.ContainsKey(locale2))
						{
#if DEBUG
							Console.WriteLine(string.Format("XmlLibraryNamespace::GetPhraseByID returning \"{0}\" (locale2)", p.Translations[locale2]));
#endif
							return p.Translations[locale2];
						}
					}
				}
			}

#if DEBUG
			Console.WriteLine(string.Format("XmlLibraryNamespace::GetPhraseByID returning \"{0}\" (fallback)", fallbackphrase));
#endif
			return fallbackphrase;
		}

		public bool RegisterPhrase(string originalphrase, string translation, CultureInfo locale)
		{
			return RegisterPhrase(originalphrase, translation, locale.Name);
		}

		public bool RegisterPhrase(string originalphrase, string translation, string locale)
		{
#if DEBUG
			Console.WriteLine(string.Format("XmlLibraryNamespace::RegisterPhrase( originalphrase=\"{0}\", translation=\"{1}\", locale=\"{2}\" );", originalphrase, translation, locale));
#endif
			if (m_library.DefaultLocale != CultureInfo.InvariantCulture)
				m_library.RegisterLocale(m_library.DefaultLocale.Name);

			if (!string.IsNullOrEmpty(locale))
				m_library.RegisterLocale(locale);

			XmlLibraryPhrase found = null;

			if (m_library.DefaultLocale != CultureInfo.InvariantCulture)
			{
				foreach (XmlLibraryPhrase p in m_phrases)
				{
					if (p.Translations[m_library.DefaultLocale.Name] == originalphrase)
					{
						found = p;
						break;
					}
				}
			}
			else
			{
				foreach (XmlLibraryPhrase p in m_phrases)
				{
					if (p.TempOriginalPhrase == originalphrase)
					{
						found = p;
						break;
					}
				}
			}

			if (found == null)
			{
				found = new XmlLibraryPhrase();
				found.ID = XmlLibraryProvider.GenerateID();// Regex.Replace(Guid.NewGuid().ToString(), "[^0-9a-z]", "");
				m_phrases.Add(found);
			}

			if (m_library.DefaultLocale != CultureInfo.InvariantCulture)
			{
				if (!found.Translations.ContainsKey(m_library.DefaultLocale.Name))
				{
#if DEBUG
					Console.WriteLine(string.Format("registering phrase \"{0}\" for default locale \"{1}\"", originalphrase, m_library.DefaultLocale.Name));
#endif
					found.Translations.Add(m_library.DefaultLocale.Name, originalphrase);
				}
			}
			else
			{
#if DEBUG
				Console.WriteLine(string.Format("registering phrase \"{0}\" for temporary default locale", originalphrase));
#endif
				found.TempOriginalPhrase = originalphrase;
			}

			if (!string.IsNullOrEmpty(translation) && !string.IsNullOrEmpty(locale))
			{
				if (!found.Translations.ContainsKey(locale))
				{
#if DEBUG
					Console.WriteLine(string.Format("registering phrase \"{0}\" for locale \"{1}\"", translation, locale));
#endif
					found.Translations.Add(locale, translation);
				}
				else
				{
#if DEBUG
					Console.WriteLine(string.Format("replacing with phrase \"{0}\" for locale \"{1}\"", translation, locale));
#endif
					found.Translations[locale] = translation;
				}
			}

			return true;
		}

		public bool RegisterPhraseID(string id, string originalphrase, string translation, CultureInfo locale)
		{
			return RegisterPhraseID(id, originalphrase, translation, locale.Name);
		}

		public bool RegisterPhraseID(string id, string originalphrase, string translation, string locale)
		{
			// string lowid = id.ToLower();
#if DEBUG
			Console.WriteLine(string.Format("XmlLibraryNamespace::RegisterPhraseID( id=\"{0}\", originalphrase=\"{1}\", translation=\"{2}\", locale=\"{3}\" );", id, originalphrase, translation, locale));
#endif
			if (m_library.DefaultLocale != CultureInfo.InvariantCulture)
				m_library.RegisterLocale(m_library.DefaultLocale.Name);

			if (!string.IsNullOrEmpty(locale))
				m_library.RegisterLocale(locale);

			XmlLibraryPhrase found = null;
			foreach (XmlLibraryPhrase p in m_phrases)
			{
				if (p.ID == id)
					found = p;
			}
		
			if (found == null)
			{
				found = new XmlLibraryPhrase();
				found.ID = id;
				m_phrases.Add(found);
			}

			if (m_library.DefaultLocale != CultureInfo.InvariantCulture)
			{
				if (!found.Translations.ContainsKey(m_library.DefaultLocale.Name))
				{
#if DEBUG
					Console.WriteLine(string.Format("registering phrase \"{0}\" for default locale \"{1}\"", originalphrase, m_library.DefaultLocale.Name));
#endif
					found.Translations.Add(m_library.DefaultLocale.Name, originalphrase);
				}
			}

			if (!string.IsNullOrEmpty(translation) && !string.IsNullOrEmpty(locale))
			{
				if (!found.Translations.ContainsKey(locale))
				{
#if DEBUG
					Console.WriteLine(string.Format("registering phrase \"{0}\" for locale \"{1}\"", translation, locale));
#endif
					found.Translations.Add(locale, translation);
				}
				else
				{
#if DEBUG
					Console.WriteLine(string.Format("replacing with phrase \"{0}\" for locale \"{1}\"", translation, locale));
#endif
					found.Translations[locale] = translation;
				}
			}

			return true;
		}

		public int PhraseCount
		{
			get
			{
				return m_phrases.Count;
			}
		}

		public List<string> GetIDs()
		{
			//	return phrases.Count;

			List<string> ids = new List<string>();

			foreach (XmlLibraryPhrase info in m_phrases)
			{
				if (!string.IsNullOrEmpty(info.ID))
					ids.Add(info.ID);
			}

			return ids;
		}

		public void Clear()
		{
			m_phrases.Clear();
		}

		public void AppendXML(XmlNode rootnode)
		{
			foreach (XmlLibraryPhrase info in m_phrases)
			{
				string phraseid = info.ID;

				if (string.IsNullOrEmpty(phraseid))
					phraseid = Guid.NewGuid().ToString();

				XmlNode pnode = rootnode.OwnerDocument.CreateElement("phrase");

				XmlAttribute idattr = pnode.OwnerDocument.CreateAttribute("id");
				idattr.Value = phraseid;
				pnode.Attributes.Append(idattr);
				/*
				XmlNode idattr = rootnode.OwnerDocument.CreateElement("id");
				idattr.AppendChild(rootnode.OwnerDocument.CreateTextNode(phraseid));
				pnode.AppendChild(idattr);
				*/
				rootnode.AppendChild(pnode);
				{
					/*
					foreach (LibraryPhraseFileReference fr in info.Refs)
					{
						XmlNode tnode = rootnode.OwnerDocument.CreateElement("ref");

						XmlAttribute fileattr = rootnode.OwnerDocument.CreateAttribute("file");
						fileattr.Value = fr.File;
						tnode.Attributes.Append(fileattr);

						XmlAttribute lineattr = rootnode.OwnerDocument.CreateAttribute("line");
						lineattr.Value = fr.Line.ToString();
						tnode.Attributes.Append(lineattr);

						pnode.AppendChild(tnode);
					}
					*/
					Dictionary<string, string>.Enumerator te = info.Translations.GetEnumerator();
					while (te.MoveNext())
					{
						//	info.Refs.GetEnumerator(

						/*

						if (te.Current.Key == m_library.DefaultLocale.Name)
						{
							XmlNode originalattr = rootnode.OwnerDocument.CreateElement("orig");

							XmlAttribute langattr = rootnode.OwnerDocument.CreateAttribute("lang");
							langattr.Value = te.Current.Key;
							originalattr.Attributes.Append(langattr);

							originalattr.AppendChild(rootnode.OwnerDocument.CreateTextNode(te.Current.Value));
							pnode.AppendChild(originalattr);
						}
						else*/
						{
							XmlNode tnode = rootnode.OwnerDocument.CreateElement("tran");

							XmlAttribute langattr = rootnode.OwnerDocument.CreateAttribute("lang");
							langattr.Value = te.Current.Key;
							tnode.Attributes.Append(langattr);
							tnode.AppendChild(rootnode.OwnerDocument.CreateTextNode(te.Current.Value));

							pnode.AppendChild(tnode);
						}
					}
				}
			}
		}

	}
}
